package ru.alt22.visor.php.unittests.finder;

import java.util.ArrayList;

import org.eclipse.core.resources.IProject;
import org.eclipse.php.internal.core.phpModel.parser.PHPProjectModel;
import org.eclipse.php.internal.core.phpModel.parser.PHPUserModel;
import org.eclipse.php.internal.core.phpModel.parser.PHPWorkspaceModelManager;
import org.eclipse.php.internal.core.phpModel.phpElementData.CodeData;
import org.eclipse.php.internal.core.phpModel.phpElementData.PHPClassData;

import ru.alt22.visor.php.core.reflection.ReflectionClass;
import ru.alt22.visor.php.core.reflection.ReflectionMethod;
import ru.alt22.visor.php.properties.Properties;
import ru.alt22.visor.php.unittests.core.PHPTestCase;
import ru.alt22.visor.php.unittests.core.PHPTestSuite;

public class DefaultFinder implements Finder {
	
	private static ReflectionClass[] EMPTY = new ReflectionClass[0];

	public PHPTestSuite find(IProject project) {
		PHPTestSuite result = new PHPTestSuite(project.getName());

		ReflectionClass[] testClasses = getTestClasses(project);
		for (int i = 0; i < testClasses.length; i++) {
			ReflectionClass testClass = testClasses[i];
			ReflectionMethod[] testMethods = testClass.getMethods();

			PHPTestSuite suite = null;
			for (int j = 0; j < testMethods.length; j++) {
				ReflectionMethod testMethod = testMethods[j];
				if (!validTestMethod(testMethod)) {
					continue;
				}
				if (null == suite) {
					suite = new PHPTestSuite(testClass.getName());
				}
				suite.addTest(new PHPTestCase(testMethod));
			}
			if (null != suite) {
				result.addTest(suite);
			}
		}

		return result;
	}

	private boolean validTestMethod(ReflectionMethod testMethod) {
		if (testMethod.getName().length() < 4) {
			return false;
		}
		if (testMethod.isAbstract()) {
			return false;
		}
		if (testMethod.isStatic()) {
			return false;
		}
		if (!testMethod.isPublic()) {
			return false;
		}
		if (0 != testMethod.getName().substring(0, 4).compareToIgnoreCase("test")) {
			return false;
		}
		return true;
	}

	public ReflectionClass[] getTestClasses(IProject project) {
		String baseClass = Properties.getBaseTestClass(project);
		if (baseClass == null) {
			return EMPTY;
		}

		ArrayList<ReflectionClass> result = new ArrayList<ReflectionClass>();

		PHPUserModel model = null;
		PHPProjectModel projectModel = PHPWorkspaceModelManager.getInstance().getModelForProject(project);
		try {
			model = projectModel.getPHPUserModel();
		} catch (Exception e) {
			return result.toArray(new ReflectionClass[0]);
		}

		CodeData[] classes = model.getClasses();
		for (int j = 0; j < classes.length; j++) {
			ReflectionClass reflection = new ReflectionClass((PHPClassData) classes[j]);
			if (!reflection.isInstantiable()) {
				continue;
			}
			if (!reflection.isSubClassOf(baseClass)) {
				continue;
			}
			result.add(reflection);
		}

		return result.toArray(new ReflectionClass[result.size()]);
	}

}
